/**
 * 
 */
package com.netscenery.yang.model;

import java.util.List;

import org.jdom2.Attribute;
import org.jdom2.Element;

import com.netscenery.util.ErrTag;
import com.netscenery.util.Unicode;
import com.netscenery.util.XMLTag;
import com.netscenery.yang.YangKeyword;
import com.netscenery.yang.YangStatement;
import com.netscenery.yang.designer.MapInfo;
import com.netscenery.yang.designer.MethodInfo;
import com.netscenery.yang.parser.YangParserException;

/**
 * @author llly
 *
 */
public class Extension extends Entity {
	private String argument;
	private boolean yinElement = false;
	
	public Extension(Env env,String name){
		this.env = env;
		
		this.setName(name);
	}

	/**
	 * @return the argument
	 */
	public String getArgument() {
		return argument;
	}

	/**
	 * @param argument the argument to set
	 */
	public void setArgument(String argument) {
		this.argument = argument;
	}

	public boolean isYinElement() {
		return yinElement;
	}

	public void setYinElement(boolean yinElement) {
		this.yinElement = yinElement;
	}


	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#validate()
	 */
	@Override
	public Validator validate() {
		Validator validator = new Validator();
		if(!checkName(this.name)){
			validator.setIsValid(false);
			validator.addMsg(new Message(this,ErrTag.ERROR,ErrorCode.COMMON_INVALIDNAME));
		}
		if (null != this.argument){
			if (!isIdentifier(this.argument)){
				validator.setIsValid(false);
				validator.addMsg(new Message(this,ErrTag.ERROR,"invalid argument."));
			}
		}
		if (!isNullString(this.description)){
			if (Unicode.containChinese(this.description)){
				validator.setIsValid(false);
				validator.addMsg(new Message(this,ErrTag.ERROR,"description",ErrorCode.INVALID_CHARACTER));
			}
		}
		
		if (!isNullString(this.reference)){
			if (Unicode.containChinese(this.reference)){
				validator.setIsValid(false);
				validator.addMsg(new Message(this,ErrTag.ERROR,"reference",ErrorCode.INVALID_CHARACTER));
			}
		}
		
		Validator sValidator = super.validate();
		validator.copy(sValidator);
		return validator;
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#toYang()
	 */
	@Override
	public YangStatement toYang() {

		YangStatement statement = new YangStatement(YangStatement.YANG_STATEMENT_EXTENSION
				,this.getName());
		if (null != this.getArgument()){
			YangStatement  argstat = new YangStatement(YangStatement.YANG_STATEMENT_ARGUMENT
					,this.argument);
			if (isYinElement()){
				YangStatement yinElement = new YangStatement(YangKeyword.YINELEMENT.getKeyword(),"true");
				argstat.addChild(yinElement);
			}
			statement.addChild(argstat);
		}
		if (null != this.getDescription()){
			YangStatement descr = new YangStatement(YangStatement.YANG_STATEMENT_DESCRIPTION
					,this.getDescription());
			statement.addChild(descr);
			
		}
		
		if (null != this.getReference()){
			YangStatement ref = new YangStatement(YangStatement.YANG_STATEMENT_REFERENCE
					,this.getReference());
			statement.addChild(ref);
		}
		
		if (Status.CURRENT != this.getStatus()){
			YangStatement status = new YangStatement(YangStatement.YANG_STATEMENT_STATUS
					,this.getStatus().getStatus());
			statement.addChild(status);
		}

		
		return statement;
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#toXML()
	 */
	@Override
	public Element toXML() {

		Element element = new Element(XMLTag.XML_TAG_EXTENSION);
		Element name = new Element(XMLTag.XML_TAG_NAME);
		name.setText(this.getName());
		element.addContent(name);

		if (null != this.getArgument()){
			Element  argstat = new Element(XMLTag.XML_TAG_ARGUMENT);
			argstat.setText(this.getArgument());
			element.addContent(argstat);
		}
		if (null != this.getDescription()){
			Element descr = new Element(XMLTag.XML_TAG_DESCRIPTION);
			descr.setText(getDescription());
			element.addContent(descr);
			
		}
		
		if (null != this.getReference()){
			Element ref = new Element(XMLTag.XML_TAG_REFERENCE);
			ref.setText(getReference());
			element.addContent(ref);
		}
		
		//if (Status.CURRENT != this.getStatus()){
			Element status = new Element(XMLTag.XML_TAG_STATUS);
			status.setText(this.getStatus().getStatus());
			element.addContent(status);
		//}
		
		return element;
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#isFieldMandatory(java.lang.String)
	 */
	@Override
	public boolean isFieldMandatory(String field) {
		// TODO Auto-generated method stub
		return false;
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#readXML(org.jdom2.Element)
	 */
	@Override
	public int readXML(Element element) throws ModelException {
		if (null == element){
			return MODELELEMENT_OK;
		}

		String value = element.getText();

		// ����
		if (element.getName().equals(
				XMLTag.XML_TAG_DESCRIPTION)) {
			this.setDescription(value);
		}
		// reference
		else if (element.getName().equals(
				XMLTag.XML_TAG_REFERENCE)) {
			this.setReference(value);
		}
		// status
		else if (element.getName().equals(
				XMLTag.XML_TAG_STATUS)) {
			this.setStatus(Status.getStatus(value));
		}
		// argument
		else if (element.getName().equals(
				XMLTag.XML_TAG_ARGUMENT)) {
			this.setArgument(value);
		}
		else if (element.getName().equals(
				XMLTag.XML_TAG_NAME)){
			return MODELELEMENT_OK;
		}
		// ������ֶ�
		else {
			return MODELELEMENT_FAIL;
		}

		return MODELELEMENT_OK;
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#readYANG(com.netscenery.modeldesigner.util.YangStatement)
	 */
	@Override
	public int readYANG(YangStatement statement) throws YangParserException {
		if (null == statement){
			return MODELELEMENT_OK;
		}
		

		YangStatement subStatement = statement;
		String value = subStatement.getArgument();

		// ����
		if (subStatement.getKeyword().equals(
				YangStatement.YANG_STATEMENT_DESCRIPTION)) {
			this.setDescription(value);
		}
		// reference
		else if (subStatement.getKeyword().equals(
				YangStatement.YANG_STATEMENT_REFERENCE)) {
			this.setReference(value);
		}
		// status
		else if (subStatement.getKeyword().equals(
				YangStatement.YANG_STATEMENT_STATUS)) {
			this.setStatus(Status.getStatus(value));
		}
		// argument
		else if (subStatement.getKeyword().equals(
				YangStatement.YANG_STATEMENT_ARGUMENT)) {
			this.setArgument(subStatement.getArgument());
			String isyinelement = subStatement.getChildArgument(YangKeyword.YINELEMENT.getKeyword());
			if ("true".equalsIgnoreCase(isyinelement)){
				this.setYinElement(true);
			}
			
		}
		// ������ֶ�
		else {
			return MODELELEMENT_FAIL;
		}

		return MODELELEMENT_OK;
	}


	public  MapInfo getMapInfo() throws SecurityException, NoSuchMethodException {
		MapInfo mapInfo = new MapInfo();
		
		mapInfo.setClazz(Extension.class);

		return mapInfo;
	}

	@Override
	public Element toYin() {
		Element statement = new Element(YangStatement.YANG_STATEMENT_EXTENSION,env.getNs());
		Attribute name = new Attribute(XMLTag.XML_TAG_NAME,this.getName());
		statement.setAttribute(name);
		if (null != this.getArgument()){
			Element  argstat = new Element(YangStatement.YANG_STATEMENT_ARGUMENT,env.getNs());
			Attribute aName = new Attribute(XMLTag.XML_TAG_NAME,this.argument);
			argstat.setAttribute(aName);
			if (isYinElement()){
				Element yinElement = new Element(YangKeyword.YINELEMENT.getKeyword(),env.getNs());
				Attribute value = new Attribute(XMLTag.XML_TAG_VALUE,"true");
				yinElement.setAttribute(value);
				argstat.addContent(yinElement);
			}
			statement.addContent(argstat);
		}
		if (null != this.getDescription()){
			Element descr = new Element(YangStatement.YANG_STATEMENT_DESCRIPTION,env.getNs());
			Element text = new Element(XMLTag.XML_TAG_TEXT,env.getNs());
			text.setText(this.getDescription());
			descr.addContent(text);
			statement.addContent(descr);
			
		}
		
		if (null != this.getReference()){
			Element ref = new Element(YangStatement.YANG_STATEMENT_REFERENCE,env.getNs());
			Element text = new Element(XMLTag.XML_TAG_TEXT,env.getNs());
			text.setText(this.getReference());
			ref.addContent(text);
			statement.addContent(ref);
		}
		
		if (Status.CURRENT != this.getStatus()){
			Element status = new Element(YangStatement.YANG_STATEMENT_STATUS,env.getNs());
			Attribute value = new Attribute(YangKeyword.VALUE.getKeyword(),this.getStatus().getStatus());
			status.setAttribute(value);
			statement.addContent(status);
		}

		
		return statement;
	}

	@Override
	public int readYin(Element statement) throws ModelException {
		if (null == statement){
			return MODELELEMENT_OK;
		}
		

		
		

		// ����
		if (statement.getName().equals(YangStatement.YANG_STATEMENT_DESCRIPTION)) {
			Element text = statement.getChild(XMLTag.XML_TAG_TEXT,env.getNs());
			if (null == text){
				return MODELELEMENT_FAIL;
			}
			this.setDescription(text.getText());
		}
		// reference
		else if (statement.getName().equals(
				YangStatement.YANG_STATEMENT_REFERENCE)) {
			Element text = statement.getChild(XMLTag.XML_TAG_TEXT,env.getNs());
			if (null == text){
				return MODELELEMENT_FAIL;
			}
			this.setReference(text.getText());
		}
		// status
		else if (statement.getName().equals(
				YangStatement.YANG_STATEMENT_STATUS)) {
			String value= statement.getAttributeValue(YangKeyword.VALUE.getKeyword());
			if (null == value){
				return MODELELEMENT_FAIL;
			}
			else {
				this.status = Status.getStatus(value);
			}
		}
		// argument
		else if (statement.getName().equals(
				YangStatement.YANG_STATEMENT_ARGUMENT)) {
			this.setArgument(statement.getAttributeValue(XMLTag.XML_TAG_NAME));
			Element yinElement = statement.getChild(YangKeyword.YINELEMENT.getKeyword(),env.getNs());
			String value = yinElement.getAttributeValue(YangKeyword.VALUE.getKeyword());
			if (null == value){
				return MODELELEMENT_FAIL;
			}
			if ("true".equals(value)){
				this.setYinElement(true);
			}
		}
		// ������ֶ�
		else {
			return MODELELEMENT_FAIL;
		}

		return MODELELEMENT_OK;
	}

	@Override
	public void update() {
		// TODO Auto-generated method stub
		
	}

}
